<template>
    <a-skeleton :animation="true" :class="[{ 'height': !chatDetail?.app }]" :style="{ 'padding-top': `${customInfoHeight}px` }">
        <div :class="['right-chat']">
            <!-- 群聊列表 -->
            <div :class="['chat', { 'height': chatDetail?.status === 1 || !isChat }]" ref="chatRef" @scroll="onScroll" @click="myTextareaRef?.focus()">
                <a-skeleton-line :rows="1" :line-height="500" v-if="!chatDetail?.id"/>
                <template v-else>
                    <div v-for="(item, itemIndex) in chatList" :key="item.id" :class="['item', { 'item-self': item.isSelf }]">
                        <div class="time" v-if="shouldShowTime(itemIndex)">{{ formatChatTime(item.sendTime, true) }}</div>
                        <div :class="['box', {'box-style': item.btnType || useUserStore().chatType.includes(item.type)}]">
                            <template v-if="item.btnType || useUserStore().chatType.includes(item.type)">
                                <div class="tips">{{ item.btnTips || item.content }}</div>
                            </template>
                            <template v-else>
                                <ComAvatar :sex="item.sex"
                                           :keys="item.initialLetter"
                                           :size="32"/>
                                <div class="info">
                                    <div class="name">
                                        <div :class="['name-box', { 'style': item.isSelf }]">
                                            {{ item.sendName || '-' }}
                                            <span class="creator" v-if="item.sendId === chatDetail?.creatorId">创建者</span>
                                            <span class="email" v-if="item.sendId !== loginId()">
                                                <a :href="'mailto:' + userList.find(child => child.id === item.sendId)?.email" class="email-link">
                                                    {{ userList.find(child => child.id === item.sendId)?.email }}
                                                </a>
                                            </span>
                                        </div>
                                    </div>
                                    <div class="msg" v-dompurify-html="item.content" @click="handleClick"></div>
                                </div>
                            </template>
                        </div>
                    </div>
                </template>
                <i class="EachApp EachApp_fanhuidibu common-bottom flex" @click="chatRef.scrollTo(0, chatRef.scrollHeight);" v-if="isBottom"></i>
            </div>
            <!-- 群聊输入框 -->
            <template v-if="isChat">
                <div class="ipt" >
                    <Tools @toolsEmit="toolsEmit" />
                    <a-skeleton-line :rows="1" :line-height="129" v-if="!chatDetail?.id"/>
                    <div class="ipt-box" v-else>
                        <div ref="myTextareaRef" :class="['sendIpt', { 'no-tips': myTextareaRef?.innerHTML }]" contenteditable="true"
                            @paste.prevent="onPaste" @keydown="handleSendMsg" @input="handleClickInput" @click="handleClickInput">
                        </div>
                    </div>
                </div>
            </template>
        </div>
    </a-skeleton>
    <!-- 预览 -->
    <a-image-preview-group
        v-model:visible="previewVisible"
        v-model:current="previewIndex"
        :srcList="previewList"
        infinite
    />
</template>
<script lang="ts" setup>
const props = defineProps({
    userList: { type: Array, default: () => { return [] } },
})
import Tools from './Tools.vue';
import * as Api from '@/api/msg';
import mitt from "@/utils/bus";
import Base64 from '@/utils/base64';
import {formatChatTime} from '@/utils/index';
import {insertImageAtCursor, resizeImageDimensions} from '@/utils/img';
import {useUserStore} from '@/store/modules/user';
import {loginId} from '@/utils/login';
import mixin from "@/mixins/index";
import {websocketStoreWithOut} from '@/store/modules/websocket';

const emit = defineEmits(['handlePreNext', 'inputVal']);
const { handleMixinSubmit } = mixin();
const newBase64 = new Base64();
const { wsCache } = useCache();
const isCollapse = ref(false);
const chatList = ref([]); // 消息列表
const chatDetail = ref({
    userIds: [],
}); // 消息详情
const chatRef = ref(null);
const chatInfo = ref({
    isLast: true, // 是否是最后一页
}); // 分页信息
const myTextareaRef = ref(null);
const currentGroupInfo = ref({}); // 当前群聊信息
const isChat = ref(true); // 是否可发送消息
const currentInsertIndex = ref(''); // 当前输入框index下标位置
const previewVisible = ref(false);
const previewList = ref([]); // 预览列表
const previewIndex = ref(0); // 预览下标
const isBottom = ref(false); // 是否到底
const customInfoHeight = ref(0); // 客户信息区域的高度
let { $state: { websocket, isConnected, imStore }, setChatList, returnMsg } = websocketStoreWithOut();

// 收到的消息-处理
const handleAddEventListener = (event) => {
    const websocketMsg = event.target.localStorage.websocketMsg;
    if(websocketMsg){
        const newValue = JSON.parse(websocketMsg);
        const data = JSON.parse(newValue?.v);
        handleOnMessage(data);
    }
}

// 收到的消息-处理
const handleOnMessage = (params, isStore = false) => {
    // 处理群聊消息等正常消息
    const { sendId, sendTime, content, topicId, type, sendType } = params;
    console.log('ws收到消息===function:', sendType, {...params});
    // SYSTEM_MESSAGE系统消息   GROUP_MESSAGE会话消息
    if(sendType === 'GROUP_MESSAGE'){
        let contentNew = content;
        if(contentNew.includes('<img')){
            contentNew = contentNew.replace(/src="([^"]*)"/g, (match, p1) => {
                const url = `${import.meta.env.VITE_PREVIEW_URL}/${p1}`;
                previewList.value.push(url.replace('.png_thumb', ''));
                return `src="${url}"`;
            });
        }
        const sendName = imStore.userList.find(child => child.id === sendId)?.nickname;
        mitt.emit('sendMsg', { sendType, sendName, ...params});
        // 是否是我自己发的消息
        const isMyself = loginId() === sendId;
        // 是否当前处于接收消息的群里(true: push新信息， 反之则no)
        const isNewMsgGroup = chatDetail.value.id === topicId;
        if(isMyself){
            if(!(useUserStore().chatType.includes(type))){
                chatList.value.push({
                    sex: imStore.userList.find(child => child.id === loginId())?.sex,
                    sendId: loginId(),
                    sendName: imStore.userList.find(child => child.id === loginId())?.nickname,
                    sendTime,
                    initialLetter: imStore.userList.find(child => child.id === loginId())?.initialLetter,
                    content: contentNew,
                    isSelf: true
                })
            }
        }else{ // 当前人发送消息不加，其他人+1
            if(type !== 32){
                if(currentGroupInfo.value.id === topicId){
                    currentGroupInfo.value.unread += 1;
                }
            }
            const { chatList, userList } = imStore;
            // console.log('chatList====', chatList, topicId);
            let items = imStore.chatList.find(item => item.topicId === topicId);
            const itemsIndex = imStore.chatList.findIndex(item => item.topicId === topicId);
            if(items){
                items = {
                    ...items,
                    sendTime,
                    sex: imStore.userList.find(child => child.id === sendId)?.sex,
                    sendName: userList?.find(child => child.id === sendId)?.nickname,
                    unread: (items?.unread || 0) + 1,
                }
                items.lastMsg.content = content?.replace(/<img.*?>/g, "[图片]").replace(/<[^>]*>/g,' ');
                imStore.chatList.splice(itemsIndex, 1);
                imStore.chatList.unshift(items);
                if(isStore){
                    setChatList(imStore.chatList);
                }
                // console.log('发送消息后=====', imStore.chatList);
            }
        }
        // 如果登录人和发送消息的人不是同一个人1
        if(!isMyself && isNewMsgGroup){
            // 删除、归档不Push消息
            if(!(useUserStore().chatType.includes(type))){
                chatList.value.push({
                    sendId,
                    sendName,
                    sendTime,
                    sex: imStore.userList.find(child => child.id === sendId)?.sex,
                    initialLetter: imStore.userList.find(child => child.id === sendId)?.initialLetter,
                    content: contentNew,
                })
            }
        }
        // 添加文字提示
        if(chatDetail.value.id === topicId && [21, 31].includes(type)){
            chatList.value.push({ ...params, sendTime });
        }
    }else if(sendType === 'SYSTEM_MESSAGE'){ // 系统消息
        mitt.emit('sendMsg', { sendType,  ...params});
    }
    handleChatBottom();
}

onMounted(() => {
    window.addEventListener('storage', handleAddEventListener);
    if(websocket && isConnected){
        websocket.onmessage = (event) => {
            if (event.data === 'pong') {
                // console.log('收到pong响应');
                websocketStoreWithOut().setPong(); // 重设pong超时计时器
            } else {
                const newValue = JSON.parse(event.data);
                const params = {
                    ...newValue.content,
                    sendType: newValue.type
                }
                handleOnMessage(params, true);
                return;
            }
        };
    }
})

onUnmounted(() => {
    window.removeEventListener('storage', handleAddEventListener);
})

// 消息详情
const getChatDetail = async (topicId, isEmpty = false) => {
    try{
        const res = await Api.ApiChatListDetail(topicId);
        chatDetail.value = res;
        customInfoHeight.value = 0;
        getChatUserList(topicId);
        await getRecordList(topicId, '', true, isEmpty);
        mitt.emit('chatDetail', chatDetail.value);
    }catch(err){console.log(err);}
}

// 获取群聊用户成员
const getChatUserList = async (topicId) => {
    try{
        const res = await Api.ApiChatListDetailUser(topicId);
        let arr = res?.filter(item => !item.isQuit) || [];
        chatDetail.value.users = arr;
        chatDetail.value.userIds = arr?.map(item => item.id);
        chatDetail.value.creatorId = arr?.find(item => item.isCreator)?.id;
    }catch(err){console.log(err);}
}

// 消息列表
const getRecordList = async (topicId, id, isBottom = true, isEmpty) => {
    if(isEmpty){
        chatList.value = [];
    }
    chatInfo.value.isLast = true;
    try{
        let res = await Api.ApiChatListRecord(topicId, { id });
        chatList.value = [...res?.data?.reverse(), ...chatList.value] || [];
        chatInfo.value = res;
        if(chatList.value.length > 0){
            chatList.value.map(item => {
                item.sex = imStore.userList.find(child => child.id === item.sendId)?.sex;
                item.sendName = imStore.userList.find(child => child.id === item.sendId)?.nickname;
                item.initialLetter = imStore.userList.find(child => child.id === item.sendId)?.initialLetter;
                item.isSelf = item.sendId === loginId();
                if(item.content.includes('<img')){
                    item.content = item.content.replace(/src="([^"]*)"/g, (match, p1) => {
                        return `src="${item.content.includes(import.meta.env.VITE_PREVIEW_URL) ? '' : `${import.meta.env.VITE_PREVIEW_URL}/`}${p1}"`;
                    });
                }
                return item;
            })
            const imgLinks = [];
            chatList.value.forEach(item => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(item.content, 'text/html');
                const imgs = doc.querySelectorAll('img');
                imgs.forEach(img => {
                    imgLinks.push(img.getAttribute('src').replace('.png_thumb', ''));
                });
            });
            previewList.value = imgLinks;
        }
        if(isBottom){
            // 默认直接滚动到底部
            let timer = setTimeout(() => {
                clearTimeout(timer);
                handleChatBottom();
                myTextareaRef.value?.focus();
            }, 0);
        }
    }catch(err){console.log(err);}
}

// 已读群聊消息
const handleReadList = async (topicId) => {
    try{
        await handleMixinSubmit(Api.ApiChatRead, topicId, '', false);
        mitt.emit('sendMsg', { sendType: 'read', topicId });
        setChatList(imStore.chatList); // 重新设置chatList
        currentGroupInfo.value.unread = 0;
    }catch(err){console.log(err);}
}

// 获取表情
const toolsEmit = ({ toolsType, values }) => {
    if(toolsType === 'emoji'){
        if (!currentInsertIndex.value) return;
        const emoji = values;
        const range = currentInsertIndex.value.cloneRange();

        // 插入表情
        range.deleteContents();
        const textNode = document.createTextNode(emoji);
        range.insertNode(textNode);

        // 调整光标位置到表情之后
        range.setStartAfter(textNode);
        range.setEndAfter(textNode);

        const selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);

        // 重新获取焦点并保存新的光标位置
        myTextareaRef.value?.focus();
        saveCursorPosition();
    }
}

// 获取当前光标位置
const saveCursorPosition = () => {
    const selection = window.getSelection();
    if (selection && selection.rangeCount > 0) {
        currentInsertIndex.value = selection.getRangeAt(0);
        // console.log('光标====', currentInsertIndex.value.startOffset);
    }
};

// 点击输入框(主要做已读消息处理) 在光标位置插入文本
const handleClickInput = () => {
    saveCursorPosition();
    const { unread, topicId } = currentGroupInfo.value;
    if(unread > 0){
        handleReadList(topicId);
    }
    nextTick(() => {
        myTextareaRef.value.scrollTo(0, myTextareaRef.value.scrollHeight);
    })
}

// 复制
const onPaste = (e) => {
    const clipboardData = e.clipboardData;
    const items = clipboardData.items;
    console.log('粘贴====', items);
    // 阻止默认的粘贴行为
    e.preventDefault();
    // 如果剪贴板包含图片
    for (let i = 0; i < items.length; i++) {
        const item = items[i];
        console.log('复制====', item.type);
        if (item.type.includes("image")) { // 复制图片
            const file = item.getAsFile();
            const reader = new FileReader();
            reader.readAsDataURL(file); // 转换为Base64
            // 获取图片宽高
            reader.onload = (e) => {
                const img = new Image();
                img.src = e.target.result;
                img.onload = function () {
                    // 原始比例
                    const originalDimensions = { width: img.width, height: img.height };
                    // 缩放比例
                    const resizedDimensions = resizeImageDimensions(originalDimensions.width, originalDimensions.height);
                    insertImageAtCursor(e.target.result, resizedDimensions.width, resizedDimensions.height);  // 插入图片到光标位置
                };
            };
        }else if(item.type.includes("text/plain")){ // 复制其他（如: 文本等）
            const text = clipboardData.getData('text/plain');
            document.execCommand('insertText', false, text);
            saveCursorPosition();
        }
    }
    nextTick(() => {
        myTextareaRef.value.scrollTo(0, myTextareaRef.value.scrollHeight);
    })
}

// 发送消息
const handleSend = async (content) => {
    if(content.trim()){
        try{
            const params = {
                type: content.includes('<img') ? 1 : 0, // 1带图片  0纯文本
                topicId: chatDetail.value.id,
                content
            }
            const res = await Api.ApiChatSend(params);
            handleChatBottom();
        }catch(err){console.log(err);}
    };
}

// 发送消息
const handleSendMsg = (event) => {
    const regex = /<(?!img\b)[^>]+>/gi;
    const innerHTML = event.target.innerHTML.replace(regex, '');
    if(!innerHTML && event.keyCode === 13){
        event.preventDefault();
    }
    let timers = setTimeout(async () => {
        clearTimeout(timers);
        emit('inputVal', innerHTML);
        if(!innerHTML){ // 没有内容才能使用上下键
            if([38, 40].includes(event.keyCode)){
                emit('handlePreNext', { preNext: event.keyCode === 38 ? 'pre' : 'next', topicId: chatDetail.value.id });
            }
        }else{
            if (event.keyCode === 13) { // 回车
                if (event.shiftKey) {
                    // 插入换行符
                    document.execCommand("insertHTML", false, "<br>");
                    saveCursorPosition();
                } else {
                    event.preventDefault();
                    const editableDiv = event.target;
                    const innerHTML = ['', '<br>'].includes(editableDiv.innerHTML) ? '' : editableDiv.innerHTML;
                    if(innerHTML){
                        const parts = editableDiv.innerHTML.split('<br>');
                        const processedParts = parts.map(part => `<p>${part ? part : '<br>'}</p>`);
                        const message = processedParts.join('').replaceAll('&nbsp;', ' ');
                        const isHave = message.replace(/<p>/g, '').replace(/<\/p>/g, '').trim();
                        const isEmpty = isHave.replace(/<br>/g, '');
                        if(isHave && isEmpty){
                            // console.log('发送消息===', isHave, isEmpty);
                            editableDiv.textContent = '';
                            emit('inputVal', '');
                            await handleSend(message);
                        }
                    }
                }
            }else if([37, 38, 39, 40].includes(event.keyCode)){ // 键盘上下左右也要获取光标位置
                // 给个延时，保证光标在最新位置
                let timer = setTimeout(() => {
                    clearTimeout(timer)
                    saveCursorPosition();
                }, 0);
            }
        }
    }, 0);
};

// 上拉加载
const onScroll = () => {
    nextTick(() => {
        const container = chatRef.value;
        isBottom.value = container.scrollHeight - (container.scrollTop + container.clientHeight) > 600;
        if (container.scrollTop <= 300 && !chatInfo.value.isLast) {
            getRecordList(currentGroupInfo.value.topicId, chatInfo.value.cursor, false);
        }
    })
}

mitt.on('handleSubmit', e => {
    handleSubmit(e);
})
// 展开、收起
mitt.on('handleCollapse', e => {
    isCollapse.value = e;
})
// 获取客户信息区域的高度
mitt.on('customInfoHeight', e => {
    customInfoHeight.value = e;
})
// 删除、归档
mitt.on('handleChatBtn', e => {
    if(e.sendType === 'del'){
        // websocket.send('群聊删除');
    }else if(e.sendType === 'return'){
        chatDetail.value.status = 1;
        // websocket.send('群聊归档');
    }
})

// 处理删除、归档、被移除等
const handleChatType = async (value) => {
    const { topicId, btnType, isDetail, unread, isFirst, lastMsg: { type, sendTime, status, sendId } } = value;
    const isChatManager = loginId() === sendId;
    console.log('群聊信息===', {...value});
    chatDetail.value.app = null;
    if(unread > 0){
        // console.log('读取消息======');
        handleReadList(topicId);
    }
    if(isDetail && topicId !== chatDetail.value.id){
        await getChatDetail(topicId, true);
        if(chatDetail.value?.status === 1){ // 已归档
            const isHave = chatList.value.some(item => item.type === 31);
            if(!isHave){
                const params = {
                    btnType: 'return',
                    btnTips: '会话已归档',
                }
                chatList.value.push(params);
            }
            isChat.value = false;
            handleChatBottom();
            return;
        }
    }
    if(btnType === 'add'){
        isChat.value = true;
    }
    // 移除群聊 归档都不能发送消息了
    if(['del', 'return', 'remove'].includes(btnType) || type === 33 || status === 1){
        isChat.value = false;
    }else{
        isChat.value = true;
    }
    // 拉人、踢人刷新群用户列表
    if(['add', 'remove'].includes(btnType)){
        getChatUserList(topicId);
        // console.log('拉人踢人===');
    }
    if(myTextareaRef.value){
        myTextareaRef.value.textContent = '';
        myTextareaRef.value.focus();
    }
    handleChatBottom();
    saveCursorPosition();
}

// 群聊置底
const handleChatBottom = () => {
    nextTick(() => {
        if(chatRef.value){
            chatRef.value.scrollTo(0, chatRef.value.scrollHeight);
        }
    })
}

// 提交-选择成员
const handleSubmit = async ({ userIds, removed, added, addLess }) => {
    console.log('选择成员===', userIds, removed, added, addLess);
    let https = Api.ApiChatUserAdd;
    if(addLess === 'less'){
        https = Api.ApiChatUserDelete;
    }
    try{
        const res = await https(chatDetail.value.id, addLess === 'add' ? added : removed.toString());
    }catch(err){console.log(err);}
    getChatUserList(currentGroupInfo.value.topicId);
}

// 预览图片
const handleClick = (event) => {
    if(event.target.tagName === 'IMG'){
        const url = event.target.src;
        previewVisible.value = true;
        const parts = url.split('/');
        const fileName = parts[parts.length - 1].replace('.png_thumb', '');
        previewIndex.value = previewList.value.findIndex(item => item.includes(fileName)) || 0;
    }
}

// 判断当前消息和上一条消息的时间差
const shouldShowTime = (index) => {
    if (index === 0) return true; // 第一条消息总是显示时间
    const currentTime = new Date(chatList.value[index].sendTime);
    const previousTime = new Date(chatList.value[index - 1].sendTime);
    const timeDifference = (currentTime - previousTime) / 1000 / 60; // 时间差，单位分钟
    return timeDifference > 2; // 如果时间差超过2分钟，显示时间
}

// 聊天区置底
const handleBottom = () => {
    chatRef.value.scrollTo(0, chatRef.value.scrollHeight);
}

defineExpose({
    handleSubmit,
    chatDetail,
    getChatDetail,
    currentGroupInfo,
    handleChatType,
    chatList,
    handleReadList
})
</script>
<style lang="scss" scoped>
.arco-skeleton{
    height: calc(100% - 60px);
    padding-top: 120px;
    &.height{
        padding-top: 0px;
    }
    .right-chat{
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: space-between;
        .chat{
            padding: 10px 10px 10px 15px;
            height: calc(100% - 180px);
            overflow: auto;
            display: flex;
            flex-direction: column;
            row-gap: 25px;
            position: relative;
            &.height{
                height: 100%;
            }
            .item{
                .box{
                    display: flex;
                    padding-right: 20%;
                    &-style{
                        padding: 0 !important;
                    }
                    :deep(.arco-avatar){
                        margin-top: 3px;
                    }
                }
                .time,
                .tips{
                    text-align: center;
                    color: #999;
                    width: 100%;
                    padding: 5px 0;
                }
                .avatar{
                    width: 50px;
                    height: 50px;
                    border-radius: 50%;
                }
                .info{
                    padding-left: 8px;
                    flex: 1;
                    .name{
                        font-weight: bold;
                        font-size: 15px;
                        margin-bottom: 3px;
                        display: flex;
                        align-items: center;
                        height: 24px;
                        &-box{
                            display: flex;
                            align-items: center;
                            &.style{
                                flex-direction: row-reverse;
                            }
                        }
                        .creator{
                            display: inline-block;
                            padding: 3px 8px;
                            background: #1677ff;
                            border-radius: 10px;
                            font-size: 11px;
                            margin: 0 8px;
                            color: white;
                        }
                        .email{
                            font-size: 14px;
                            margin-left: 5px;
                            font-weight: normal;
                            display: none;
                        }
                    }
                    .msg{
                        font-size: 14px;
                        background: #e1e1e3;
                        border: var(--border);
                        padding: 6px 10px;
                        border-radius: 6px;
                        display: inline-block;
                        line-height: 18px;
                        text-align: justify;
                    }
                    &:hover{
                        .email{
                            display: block;
                        }
                    }
                }
                &-self{
                    .box{
                        justify-content: right;
                        flex-direction: row-reverse;
                        padding-left: 20%;
                        padding-right: 0;
                        .info{
                            text-align: right;
                            padding-right: 8px;
                            .msg{
                                font-size: 14px;
                                border: none;
                                background: #c3e0f8;
                                text-align: left;
                                text-align: justify;
                            }
                            .name{
                                justify-content: end;
                            }
                        }
                    }
                }
                :deep(.msg){
                    img{
                        height: 200px;
                        &:not(:last-child){
                            margin-bottom: 6px;
                        }
                    }
                }
                /* 默认状态，灰色字体 */
                .email-link {
                    color: gray;
                    text-decoration: none; /* 去掉下划线 */
                    transition: color 0.3s, text-decoration 0.3s; /* 平滑过渡效果 */
                }

                /* 鼠标悬停时显示下划线并改变颜色 */
                .email-link:hover {
                    color: #1890ff; /* 悬停时的字体颜色 */
                    text-decoration: underline; /* 悬停时添加下划线 */
                }
            }
        }
        .ipt{
            border-top: var(--border);
            padding: 10px;
            &-box{
                height: 129px;
                padding: 0;
                background-color: rgb(242,243,245);
                padding: 10px;
                border-radius: 4px;
            }
            :deep(.sendIpt){
                font-size: 14px;
                height: 100%;
                font-size: 14px;
                overflow: auto;
                &:focus-visible{
                    outline: initial;
                }
                img{
                    display: inline-block !important;
                }
            }
        }
    }
}
</style>